﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using NCalculator.Operations;

namespace NCalculator
{
    public partial class MainWindow : Form
    {
        #region Attributes
        private Visualization _visualization;
        private Solve _solve;
        private List<Node> _equationList;
        private bool _operator; // is operator pressed
        private bool _median;
        private MedianNode _medianNode; // ugly
        private HistoryContainer _historyContainer;
        private History _history;
        #endregion

        [DllImport("user32.dll")]
        static extern bool HideCaret(IntPtr hWnd);

        public MainWindow()
        {
            InitializeComponent();
            _visualization = new Visualization(textBoxEquation, textBoxInputValue);

            _history = new History();
            _historyContainer = new HistoryContainer();
            _solve = new Solve(_historyContainer);

            textBoxInputValue.TextAlign = HorizontalAlignment.Right;
            _equationList = new List<Node>();
            _operator = false;
            _median = false;

            _history.LoadHistory();
        }

        #region Hide caret in textBoxInputValue
        private void textBoxInputValue_MouseEnter(object sender, EventArgs e)
        {
            HideCaret(textBoxInputValue.Handle);
        }

        private void textBoxInputValue_Enter(object sender, EventArgs e)
        {
            HideCaret(textBoxInputValue.Handle);
        }

        private void textBoxInputValue_MouseDown(object sender, MouseEventArgs e)
        {
            HideCaret(textBoxInputValue.Handle);
        }

        private void textBoxInputValue_MouseLeave(object sender, EventArgs e)
        {
            HideCaret(textBoxInputValue.Handle);
        }

        private void textBoxInputValue_KeyPress(object sender, KeyPressEventArgs e)
        {
            e.Handled = true;
        }
        #endregion

        #region Buttons right part
        private void simpleButtonOne_Click(object sender, EventArgs e)
        {
            _visualization.InsertValue("1");
            _operator = false;
        }

        private void simpleButtonTwo_Click(object sender, EventArgs e)
        {
            _visualization.InsertValue("2");
            _operator = false;
        }

        private void simpleButtonThree_Click(object sender, EventArgs e)
        {
            _visualization.InsertValue("3");
            _operator = false;
        }

        private void simpleButtonFour_Click(object sender, EventArgs e)
        {
            _visualization.InsertValue("4");
            _operator = false;
        }

        private void simpleButtonFive_Click(object sender, EventArgs e)
        {
            _visualization.InsertValue("5");
            _operator = false;
        }

        private void simpleButtonSix_Click(object sender, EventArgs e)
        {
            _visualization.InsertValue("6");
            _operator = false;
        }

        private void simpleButtonSeven_Click(object sender, EventArgs e)
        {
            _visualization.InsertValue("7");
            _operator = false;
        }

        private void simpleButtonNine_Click(object sender, EventArgs e)
        {
            _visualization.InsertValue("9");
            _operator = false;
        }

        private void simpleButtonOneBack_Click(object sender, EventArgs e)
        {
            _visualization.RemoveLastChar();
            _operator = false;
        }

        private void simpleButtonZero_Click(object sender, EventArgs e)
        {
            _visualization.InsertValue("0");
            _operator = false;
        }

        private void simpleButtonComma_Click(object sender, EventArgs e)
        {
            _visualization.InsertValue(",");
            _operator = false;
        }

        private void simpleButtonClear_Click(object sender, EventArgs e)
        {
            _visualization.ClearInputValue();
            _operator = false;
        }

        private void simpleButtonEight_Click(object sender, EventArgs e)
        {
            _visualization.InsertValue("8");
            _operator = false;
        }
        #endregion

        /// <summary>
        /// User can using keyboard for type numbers
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainWindow_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (char.IsDigit(e.KeyChar) || e.KeyChar == ',')
            {
                _visualization.InsertValue(e.KeyChar.ToString());
                e.Handled = true;
            }
            else if (e.KeyChar == 8) // backspace
            {
                _visualization.RemoveLastChar();
                e.Handled = true;
            }
        }

        #region Special functions
        private void simpleButtonAddition_Click(object sender, EventArgs e)
        {
            MakeOperation(new AdditionNode());
        }

        private void simpleButtonEquals_Click(object sender, EventArgs e)
        {
            if (_median)
            {
                ValueNode newNode = new ValueNode(_visualization.InputValue);
                _medianNode.AddElement(newNode);
                _visualization.MedianInsertValue(newNode.ToString());
                return;
            }

            _operator = false;
            // if user click equals when equation looks like 2 + automaticly fill it up to form 2 + 2
            if (_equationList.Count == 2) 
            {
                ValueNode newNode = new ValueNode(_visualization.InputValue);
                _solve.InsertValue(_equationList[0]);
                _solve.InsertValue(_equationList[1]);
                _solve.InsertValue(newNode);
                _visualization.AddValueToHistory(newNode);

                try
                {
                    _visualization.AddResultToHistory(_solve.Evaluation().ToString());
                    // TODO save to history
                    _equationList.Clear();

                }
                catch (Exception ex)
                {
                    _visualization.AddResultToHistory(ex.Message);
                    _equationList.Clear();
                }
            }
            else if(_equationList.Count > 2) // equation in form 2 + 3 - 7, 
            {
                ValueNode newNode = new ValueNode(_visualization.InputValue);
                _equationList.Add(newNode);

                foreach (Node n in _equationList)
                {
                    _solve.InsertValue(n);
                }
                _visualization.AddValueToHistory(newNode);

                try
                {
                    _visualization.AddResultToHistory(_solve.Evaluation().ToString());
                }
                catch (Exception ex)
                {
                    _visualization.AddResultToHistory(ex.Message);
                    _equationList.Clear();
                }

                // TODO save to history
                _equationList.Clear();
            }
        }

        private void simpleButtonSubstraction_Click(object sender, EventArgs e)
        {
            MakeOperation(new SubstractionNode());
        }

        private void simpleButtonMultiplication_Click(object sender, EventArgs e)
        {
            MakeOperation(new MultiplicationNode());
        }

        /// <summary>
        /// Add operation to history, and command list 
        /// </summary>
        /// <param name="opNode">Type of operation</param>
        private void MakeOperation(OperationNode opNode)
        {
            // operators like +,-,* is used blocking enter multi operations node
            if (!_operator)
            {
                _operator = true;
                ValueNode newNode = new ValueNode(_visualization.InputValue);
                _equationList.Add(newNode);
                _equationList.Add(opNode);

                _visualization.AddValueToHistory(newNode);
                _visualization.AddOperationToHistory(opNode);
            }
        }

        private void simpleButtonFibonacci_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            _operator = false;
            ValueNode newNode = new ValueNode(_visualization.InputValue);
            FibonacciNode fibNod = new FibonacciNode();
            fibNod.N = Convert.ToInt32(newNode.ToString()); 

            _visualization.AddSepcialFncToHistory(fibNod);
            if (_equationList.Count == 0)
            {
                _visualization.AddResultToHistory(fibNod.Evaluation().ToString());
                _equationList.Add(fibNod);

                // TODO save to history
                _equationList.Clear();
            }
            else if (_equationList.Count > 0)
            {
                _equationList.Add(fibNod);

                foreach (Node n in _equationList)
                {
                    _solve.InsertValue(n);
                }
                _visualization.AddResultToHistory(_solve.Evaluation().ToString());

                // TODO save to history
                _equationList.Clear();
            }
            this.Cursor = Cursors.Default;
        }

        private void simpleButtonSub_Click(object sender, EventArgs e)
        {
            MakeOperation(new DivisionNode());
        }

        private void simpleButtonPower_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            _operator = false;
            ValueNode newNode = new ValueNode(_visualization.InputValue);
            PowerNode powerNode = new PowerNode(newNode.Evaluation());

            _visualization.AddSepcialFncToHistory(powerNode);
            if (_equationList.Count == 0)
            {
                _visualization.AddResultToHistory(powerNode.Evaluation().ToString());
                _equationList.Add(powerNode);

                // TODO save to history
                _equationList.Clear();
            }
            else if (_equationList.Count > 0)
            {
                _equationList.Add(powerNode);

                foreach (Node n in _equationList)
                {
                    _solve.InsertValue(n);
                }
                try
                {
                    _visualization.AddResultToHistory(_solve.Evaluation().ToString());
                }
                catch (Exception ex)
                {
                    _visualization.AddResultToHistory(ex.Message);
                    _equationList.Clear();
                }

                // TODO save to history
                _equationList.Clear();
            }
            this.Cursor = Cursors.Default;

        }

        private void simpleButtonMedian_Click(object sender, EventArgs e)
        {
            if (!_median)
            {
                _median = true;
                _medianNode = new MedianNode();
                _visualization.MedianStart();
            }
            else
            {
                _median = false;
                _visualization.MedianEnd(_medianNode.Evaluation().ToString());
            }
        }
        #endregion

        private void textBoxEquation_TextChanged(object sender, EventArgs e)
        {
            // autoscroll for history window
            textBoxEquation.SelectionStart = textBoxEquation.Text.Length;
            textBoxEquation.SelectionLength = 0;
            textBoxEquation.ScrollToCaret();
        }

        private void MainWindow_FormClosing(object sender, FormClosingEventArgs e)
        {
            // saving history before close
            _history.SaveHistoryContainer(_historyContainer);
        }

        private void historyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            HistoryDialog dialog = new HistoryDialog(_history);
            DialogResult result = dialog.ShowDialog();

            // loading selected history
            if (result == System.Windows.Forms.DialogResult.OK)
            {
                HistoryContainer container = _history.HistoryList[dialog.RowIndex];

                foreach (SingleHistoryLine sl in container.HistoryList)
                {
                    foreach (Node n in sl.List)
                    {
                        _solve.InsertValue(n);
                    }
                    _visualization.LoadHistory(_solve.ToString(), _solve.Evaluation().ToString());
                }
            }
        }
    }
}
